home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbdatabs / vbdfile.cpp < prev    next >
C/C++ Source or Header  |  1999-03-18  |  54KB  |  1,819 lines

  1. // ------------------------------- //
  2. // -------- Start of File -------- //
  3. // ------------------------------- //
  4. // ----------------------------------------------------------- // 
  5. // C++ Source Code File Name: vbdfile.cpp 
  6. // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
  7. // Produced By: Doug Gaer  
  8. // File Creation Date: 02/04/1997 
  9. // Date Last Modified: 03/18/1999
  10. // Copyright (c) 1997 Douglas M. Gaer
  11. // ----------------------------------------------------------- // 
  12. // ------------- Program Description and Details ------------- // 
  13. // ----------------------------------------------------------- // 
  14. /*
  15. The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
  16. All those who put this code or its derivatives in a commercial
  17. product MUST mention this copyright in their documentation for
  18. users of the products in which this code or its derivative
  19. classes are used. Otherwise, you have the freedom to redistribute
  20. verbatim copies of this source code, adapt it to your specific
  21. needs, or improve the code and release your improvements to the
  22. public provided that the modified files carry prominent notices
  23. stating that you changed the files and the date of any change.
  24.  
  25. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
  26. THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
  27. IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
  28. YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
  29. CORRECTION.
  30.  
  31. The VBD file manager class is responsible for handling all
  32. low-level file operations through the use of VBDFile objects
  33. or by inheriting the VBDFile class. Low-level file operations
  34. refer to functions such as: Create(), Open(), Read(), Write(),
  35. Alloc(), Delete(), and Close(). These functions contain all the
  36. routines needed to create and maintain VBD files in accordance
  37. with the VBD File Format. VBDFile objects are reference counted
  38. and must be created dynamically due to the way reference
  39. counting is implemented. 
  40. */
  41. // ----------------------------------------------------------- // 
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #include <errno.h>
  45. #include "vbdfile.h"
  46.  
  47. // Define the __DOS_INCLUDES__ macro to use DOS path separators
  48. #ifdef __DOS_INCLUDES__
  49. #include <sys\types.h>
  50. #include <sys\stat.h>
  51. #else
  52. #include <sys/types.h>
  53. #include <sys/stat.h>
  54. #endif
  55.  
  56. // Init all the static data members
  57. static char ClosedFileName[MaxNameLength] = "closed.vbd";
  58.  
  59. // Current VBD file manager version number.
  60. // 07/22/1998 changed to version 1025 from version 1024.
  61. // 08/31/1998 changed to version 1027 from version 1025.
  62. // 02/10/1999 changed to version 1029 from version 1027.
  63. // 03/18/1999 changed to from version 1029 to final release version 1031.
  64. __LWORD__ VBDFile::VBDVersion = 1031;
  65.  
  66. // 08/31/1998 added revision letter 'A' to signature. Revision 'A'
  67. // adds a 32-bit checksum routines, not included in previous versions.
  68. __SBYTE__ VBDFile::VBDSignature[8] = {'V', 'B', 'D', 'F', 'I', 'L', 'E', 'A'};
  69.  
  70. VBDFile::VBDFile()
  71. // Creates a VBD file object, with refcount of one.
  72. {
  73.   strcpy(FileName, ClosedFileName); // Set the initial file name
  74.   fp = 0;
  75.   Status = 0x01; // good, read-only, and closed
  76. }
  77.  
  78. VBDFile::~VBDFile()
  79. {
  80.   Close();
  81. }
  82.  
  83. int VBDFile::Create(const char *FName, FAU StaticSize)
  84. // Creates and opens a new file named FName, truncating it
  85. // if it already exists. The area at the front of the file
  86. // of length StaticSize + sizeof(FileHeader) is reserved.
  87. {
  88.   // First, close the current file if open.
  89.   Close();
  90.  
  91.   Status = 0x05; // Set read/write bit and good bit
  92.  
  93.   // Create, truncate if already exists
  94.   fp = ::fopen(FName, "w+b");
  95.  
  96.   if(fp == 0) {
  97. #ifdef CPP_EXCEPTIONS
  98.     throw CFileCreationError();
  99. #else
  100.     Error->SignalException(EHandler::FileCreationError);
  101. #endif
  102.   }
  103.   else {
  104.     Status |= 2; // Set open bit
  105.     strcpy(FileName, FName);
  106.     Header.HeapStart = StaticSize + sizeof(FileHeader);
  107.     LastOperation = READ; // So Write() works right the first time
  108.     InitHdr();
  109.   }
  110.  
  111.   // Returns 1 if the file was successfully created and opened.
  112.   return IsOpen(); 
  113. }
  114.  
  115. void VBDFile::InitHdr()
  116. // Sets up the header area in the file. If there's
  117. // statically allocated data beyond the header, write
  118. // a 0 to the last byte of it, so that there will be no
  119. // unexpected end of file errors. The rest of the static
  120. // area stays uninitialized.
  121. {
  122.   Header.FreeSpace = 0;
  123.   Header.EndOfFile = Header.HeapStart;
  124.   Header.HighestVB = 0; // No blocks allocated in the file 
  125.   memcpy(Header.Signature, VBDSignature, 8); // Copy signature
  126.   Header.Version = VBDVersion;
  127.  
  128.   // Set the revision letter 
  129.   char revision[8];
  130.   memmove(revision, VBDSignature, 8);
  131.   rev_letter = revision[7];
  132.  
  133.   // 03/13/1998: Write the VBD file header and flush the disk
  134.   // buffers to maintain file integrity during multiple file
  135.   // access.
  136.   WriteHdr();
  137.   
  138.   if(Header.HeapStart > sizeof(FileHeader)) {
  139.      __SBYTE__ zero_byte = 0;
  140.      Write(&zero_byte, 1, Header.HeapStart-1);
  141.   }
  142. }
  143.  
  144. int VBDFile::Open(const char *FName, AccessMode Mode)
  145. // Opens the FName file. File must exist and be a VBDFile type 
  146. // or error occurs. This function will check the revsion letter
  147. // when opening an existing file.
  148. {
  149.   char *mode_str;
  150.  
  151.   // First, close the current file if open.
  152.   Close();
  153.   
  154.   if(Mode == READONLY) {
  155.     mode_str = "rb";
  156.     Status = 0x01; // set good bit, reset read/write bit
  157.   }
  158.   else {
  159.     mode_str = "r+b";
  160.     Status = 0x05; // Set good bit and read/write bit
  161.   }
  162.  
  163.   fp = ::fopen(FName, mode_str);
  164.   
  165.   if(fp == 0) {
  166. #ifdef CPP_EXCEPTIONS
  167.     throw CFileOpenError();
  168. #else
  169.     Error->SignalException(EHandler::FileOpenError);
  170. #endif
  171.   }
  172.   else {
  173.     Status |= 2; // Set open bit
  174.     strcpy(FileName, FName);
  175.     LastOperation = WRITE; // So Read() works right the first time
  176.     
  177.     ReadHdr();
  178.     // Test file type, checking the revision letter
  179.     if(memcmp(Header.Signature, VBDSignature, 7)) { 
  180. #ifdef CPP_EXCEPTIONS
  181.        throw CWrongFileType();
  182. #else
  183.        Error->SignalException(EHandler::WrongFileType);
  184. #endif
  185.     }
  186.  
  187.     // Set the revision letter according to the file header
  188.     char revision[8];
  189.     memmove(revision, Header.Signature, 8);
  190.     rev_letter = revision[7];
  191.   }
  192.  
  193.   // 03/11/1998: This code was added to ensure that true end of
  194.   // file is stored in the VBD file header. 
  195.   INT32 filesize;
  196.   filesize = FileSize(FName);
  197.   if(Header.EndOfFile < filesize) {
  198.     Header.EndOfFile = filesize;
  199.     Flush();
  200.   }
  201.   
  202.   return IsOpen(); // Returns 1 if file opened successfully, else 0.
  203. }
  204.  
  205. int VBDFile::ReOpen(const char *FName, AccessMode Mode)
  206. // Reopens the FName file. File must exist and be a VBD file type 
  207. // or error occurs. This function will check the revsion letter
  208. // when reopening an existing file.
  209. {
  210.   char *mode_str;
  211.   
  212.   if(Mode == READONLY) {
  213.     mode_str = "rb";
  214.     Status = 0x01; // set good bit, reset read/write bit
  215.   }
  216.   else {
  217.     mode_str = "r+b";
  218.     Status = 0x05; // Set good bit and read/write bit
  219.   }
  220.  
  221.   // Close the file and flush all buffers 
  222.   ::rewind(fp);
  223.   if(!ReadOnly()) ::fflush(fp);
  224.   ::fclose(fp);
  225.  
  226.   // Reopen after closing the file
  227.   fp = ::fopen(FName, mode_str);
  228.  
  229.   if(fp == 0) {
  230. #ifdef CPP_EXCEPTIONS
  231.     throw CFileOpenError();
  232. #else
  233.     Error->SignalException(EHandler::FileOpenError);
  234. #endif
  235.   }
  236.   else {
  237.     Status |= 2; // Set open bit
  238.     strcpy(FileName, FName);
  239.     LastOperation = WRITE; // So Read() works right the first time
  240.     
  241.     ReadHdr();
  242.     // Test file type, checking the revision letter
  243.     if(memcmp(Header.Signature, VBDSignature, 7)) { 
  244. #ifdef CPP_EXCEPTIONS
  245.        throw CWrongFileType();
  246. #else
  247.        Error->SignalException(EHandler::WrongFileType);
  248. #endif
  249.     }
  250.  
  251.     // Set the revision letter according to the file header
  252.     char revision[8];
  253.     memmove(revision, Header.Signature, 8);
  254.     rev_letter = revision[7];
  255.   }
  256.  
  257.   // 03/11/1998: This code was added to ensure that true end of
  258.   // file is stored in the VBD file header. 
  259.   INT32 filesize;
  260.   fi